<?php

namespace app\modules\customer\controllers;

use app\common\service\ConstantMapService;
use app\common\service\PayOrderService;
use app\common\service\UrlService;
use app\common\service\UtilService;
use app\common\service\weixin\PayApiService;
use app\models\oauth\OauthMemberBind;
use app\models\pay\PayOrder;
use app\modules\customer\common\BaseController;
use yii\log\FileTarget;

class PayController extends BaseController
{

    public function actionBuy()
    {
        $pay_order_id = intval($this->get("pay_order_id", 0));
        $reback_url = UrlService::buildCustomerUrl("/user/index");
        if (!$pay_order_id) {
            return $this->redirect($reback_url);
        }

        $pay_order_info = PayOrder::find()->where(['member_id' => $this->current_user['id'], 'id' => $pay_order_id, 'status' => -8])->one();
        if (!$pay_order_info) {
            return $this->redirect($reback_url);
        }

        return $this->render('buy', [
            'pay_order_info' => $pay_order_info
        ]);
    }

    public function actionPrepare()
    {
        $pay_order_id = intval($this->post("pay_order_id", 0));
        if (!$pay_order_id) {
            return $this->renderJSON([], "系统繁忙，请稍后再试~~", -1);
        }

        if (!UtilService::isWechat()) {
            return $this->renderJSON([], "仅支持微信支付，请将页面链接粘贴至微信打开", -1);
        }

        $pay_order_info = PayOrder::find()->where(['member_id' => $this->current_user['id'], 'id' => $pay_order_id, 'status' => -8])->one();
        if (!$pay_order_info) {
            return $this->renderJSON([], ConstantMapService::$default_syserror, -1);
        }

        $openid = $this->getOpenId();
        if (!$openid) {
            $err_msg = "购买前请绑微信~~";
            return $this->renderJSON([], $err_msg, -1);
        }

        /*请求微信paysign或者支付宝接口*/

        $config_weixin = \Yii::$app->params['weixin'];
        $wx_target = new PayApiService($config_weixin);

        $notify_url = $config_weixin['pay']['notify_url']['m'];//从配置中回去回调地址

        $wx_target->setParameter("appid", $config_weixin['appid']);
        $wx_target->setParameter("mch_id", $config_weixin['pay']['mch_id']);
        $wx_target->setParameter("openid", $openid);
        $wx_target->setParameter("body", $pay_order_info['note']);//商品描述
        $wx_target->setParameter("out_trade_no", $pay_order_info['order_sn']);//商户订单号
        $wx_target->setParameter("total_fee", $pay_order_info['pay_price'] * 100);//总金额
        $wx_target->setParameter("notify_url", UrlService::buildCustomerUrl($notify_url));//通知地址
        $wx_target->setParameter("trade_type", "JSAPI");//交易类型

        $prepayInfo = $wx_target->getPrepayInfo();
        if (!$prepayInfo) {
            return false;
        }

        $wx_target->setPrepayId($prepayInfo['prepay_id']);
        return $this->renderJSON($wx_target->getParameters());
    }

    public function actionCallback()
    {

        if (!\Yii::$app->request->isPost) {
            return $this->payEcho(false);
        }

        $check_ret = $this->OrderCallbackCheck();

        if (!$check_ret) {
            return $this->payEcho(false);
        }
        $client_type = $check_ret['client_type'];

        $order_sn = $check_ret['order_sn'];

        $pay_order_info = PayOrder::findOne(['order_sn' => $order_sn]);
        if (!$pay_order_info) {
            return $this->payEcho(false, $client_type);
        }

        if ($client_type == "wechat" && intval(strval($pay_order_info['pay_price'] * 100)) != $check_ret['total_fee']) { //微信单位为分
            return $this->payEcho(false, $client_type);
        }

        if ($pay_order_info['status'] == 1) {
            return $this->payEcho(true, $client_type);
        }

        $params = [
            'pay_sn' => $check_ret['transaction_id'],
            'callback_data' => ''
        ];

        PayOrderService::orderSuccess($pay_order_info['id'], $params);
        //记录支付回调信息
        PayOrderService::setPayOrderCallbackData($pay_order_info['id'], 'pay', $check_ret['callback_data']);
        return self::payEcho(true, $client_type);
    }

    protected function OrderCallbackCheck()
    {

        $xml = file_get_contents("php://input");
        $config_weixin = \Yii::$app->params['weixin'];
        $wx_target = new PayApiService($config_weixin);
        $wx_ret = $wx_target->xmlToArray($xml);
        $this->recordCallback($xml);

        if (!$wx_ret) {
            return false;
        }

        if ($wx_ret['return_code'] == "FAIL" || $wx_ret['result_code'] == "FAIL") {
            return false;
        }

        if (!isset($wx_ret['sign'])) {
            return false;
        }

        $order_sn = $wx_ret['out_trade_no'];

        foreach ($wx_ret as $_key => $_val) {
            if (in_array($_key, ['sign'])) {
                continue;
            }
            $wx_target->setParameter($_key, $_val);
        }

        if (!$wx_target->checkSign($wx_ret['sign'])) {
            return false;
        }

        return [
            'result_code' => 'SUCCESS',
            'client_type' => "wechat",
            'order_sn' => $order_sn,
            'total_fee' => $wx_ret['total_fee'],
            'transaction_id' => $wx_ret['transaction_id'],
            'openid' => $wx_ret['openid'],
            'callback_data' => $xml
        ];
    }

    protected function payEcho($flag = true, $client_type = "wechat")
    {
        $return_code = $flag ? "SUCCESS" : "FAIL";
        $return_msg = $flag ? "OK" : "FAIL";
        if ($client_type == "alipay") {
            $xml = $return_code;
        } else {
            $xml = <<<EOF
<xml>
   <return_code><![CDATA[{$return_code}]]></return_code>
   <return_msg><![CDATA[{$return_msg}]]></return_msg>
</xml>
EOF;
        }

        return $xml;
    }

    private function getOpenId()
    {
        $openid = $this->getCookie($this->auth_cookie_current_openid, '');

        if (!$openid) {
            $openid_info = OauthMemberBind::findOne(['member_id' => $this->current_user['id'], 'type' => 1]);
            if (!$openid_info || !isset($openid_info['openid'])) {
                return false;
            }
            $openid = $openid_info['openid'];
        }

        return $openid;
    }

    protected function recordCallback($xml)
    {
        $log = new FileTarget();
        $log->logFile = \Yii::$app->getRuntimePath() . "/logs/online_pay_" . date("Ymd") . ".log";
        $log->messages[] = [
            "[url:{$_SERVER['REQUEST_URI']}],[xml data:{$xml}]",
            1,
            'application',
            time()
        ];
        $log->export();
    }
}